﻿import pygame
import sys
import random
import math
from pygame.locals import *

# 初始化 Pygame
pygame.init()

# 设置窗口
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('太空射击游戏')

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)

# 设置时钟
clock = pygame.time.Clock()
FPS = 60

# 精灵类
class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((50, 50))
        self.image.fill(RED)
        pygame.draw.polygon(self.image, WHITE, [(25, 0), (0, 50), (50, 50)])
        self.rect = self.image.get_rect()
        self.rect.centerx = WINDOW_WIDTH // 2
        self.rect.bottom = WINDOW_HEIGHT - 10
        self.speed = 8
        self.health = 100
        self.shoot_delay = 250  # 毫秒
        self.last_shot = pygame.time.get_ticks()

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[K_LEFT]:
            self.rect.x -= self.speed
        if keys[K_RIGHT]:
            self.rect.x += self.speed
        if keys[K_UP]:
            self.rect.y -= self.speed
        if keys[K_DOWN]:
            self.rect.y += self.speed
        
        # 限制在屏幕内
        self.rect.left = max(0, self.rect.left)
        self.rect.right = min(WINDOW_WIDTH, self.rect.right)
        self.rect.top = max(0, self.rect.top)
        self.rect.bottom = min(WINDOW_HEIGHT, self.rect.bottom)
        
        # 自动射击
        now = pygame.time.get_ticks()
        if now - self.last_shot > self.shoot_delay:
            self.shoot()
            self.last_shot = now

    def shoot(self):
        bullet = Bullet(self.rect.centerx, self.rect.top)
        all_sprites.add(bullet)
        bullets.add(bullet)
        # 播放射击音效
        if shoot_sound:
            shoot_sound.play()

class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((30, 30))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(WINDOW_WIDTH - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(1, 5)
        self.speedx = random.randrange(-3, 3)

    def update(self):
        self.rect.y += self.speedy
        self.rect.x += self.speedx
        
        # 如果敌人离开屏幕，重新生成
        if (self.rect.top > WINDOW_HEIGHT or 
            self.rect.left < -25 or self.rect.right > WINDOW_WIDTH + 25):
            self.rect.x = random.randrange(WINDOW_WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(1, 5)
            self.speedx = random.randrange(-3, 3)

class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((5, 10))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y
        self.speedy = -10

    def update(self):
        self.rect.y += self.speedy
        # 如果子弹离开屏幕，删除它
        if self.rect.bottom < 0:
            self.kill()

class Star:
    def __init__(self):
        self.x = random.randrange(0, WINDOW_WIDTH)
        self.y = random.randrange(0, WINDOW_HEIGHT)
        self.size = random.randrange(1, 3)
        self.speed = random.randrange(1, 3)
        self.color = (random.randrange(150, 255), 
                      random.randrange(150, 255), 
                      random.randrange(150, 255))

    def update(self):
        self.y += self.speed
        if self.y > WINDOW_HEIGHT:
            self.y = 0
            self.x = random.randrange(0, WINDOW_WIDTH)

    def draw(self, surface):
        pygame.draw.circle(surface, self.color, (self.x, self.y), self.size)

# 加载音效
def load_sounds():
    try:
        shoot_sound = pygame.mixer.Sound('laser.wav')
        explosion_sound = pygame.mixer.Sound('explosion.wav')
        return shoot_sound, explosion_sound
    except:
        print("无法加载音效文件")
        return None, None

# 绘制文本
def draw_text(surface, text, size, x, y, color=WHITE):
    font = pygame.font.Font(None, size)
    text_surface = font.render(text, True, color)
    text_rect = text_surface.get_rect()
    text_rect.midtop = (x, y)
    surface.blit(text_surface, text_rect)

# 绘制血条
def draw_health_bar(surface, x, y, health):
    if health < 0:
        health = 0
    BAR_LENGTH = 100
    BAR_HEIGHT = 10
    fill = (health / 100) * BAR_LENGTH
    outline_rect = pygame.Rect(x, y, BAR_LENGTH, BAR_HEIGHT)
    fill_rect = pygame.Rect(x, y, fill, BAR_HEIGHT)
    pygame.draw.rect(surface, GREEN, fill_rect)
    pygame.draw.rect(surface, WHITE, outline_rect, 2)

# 显示开始画面
def show_start_screen():
    screen.fill(BLACK)
    draw_text(screen, "太空射击游戏", 64, WINDOW_WIDTH // 2, WINDOW_HEIGHT // 4)
    draw_text(screen, "使用方向键移动，自动射击", 22, WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)
    draw_text(screen, "按任意键开始", 18, WINDOW_WIDTH // 2, WINDOW_HEIGHT * 3 // 4)
    pygame.display.flip()
    
    waiting = True
    while waiting:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                waiting = False

# 显示游戏结束画面
def show_game_over_screen(score):
    screen.fill(BLACK)
    draw_text(screen, "游戏结束", 64, WINDOW_WIDTH // 2, WINDOW_HEIGHT // 4)
    draw_text(screen, f"得分: {score}", 36, WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)
    draw_text(screen, "按任意键重新开始", 24, WINDOW_WIDTH // 2, WINDOW_HEIGHT * 3 // 4)
    pygame.display.flip()
    
    waiting = True
    while waiting:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYUP:
                waiting = False

# 创建星星背景
def create_stars(count):
    stars = []
    for i in range(count):
        stars.append(Star())
    return stars

# 游戏主循环
def game_loop():
    # 创建精灵组
    global all_sprites, bullets, enemies
    all_sprites = pygame.sprite.Group()
    bullets = pygame.sprite.Group()
    enemies = pygame.sprite.Group()
    
    # 创建玩家
    player = Player()
    all_sprites.add(player)
    
    # 创建敌人
    for i in range(8):
        enemy = Enemy()
        all_sprites.add(enemy)
        enemies.add(enemy)
    
    # 创建星星背景
    stars = create_stars(100)
    
    # 游戏变量
    score = 0
    running = True
    game_over = False
    
    # 游戏循环
    while running:
        # 保持循环以正确的速度运行
        clock.tick(FPS)
        
        # 处理输入事件
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
        
        if not game_over:
            # 更新
            all_sprites.update()
            
            # 更新星星
            for star in stars:
                star.update()
            
            # 检查子弹与敌人的碰撞
            hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
            for hit in hits:
                score += 10
                # 播放爆炸音效
                if explosion_sound:
                    explosion_sound.play()
                # 生成新敌人
                enemy = Enemy()
                all_sprites.add(enemy)
                enemies.add(enemy)
            
            # 检查玩家与敌人的碰撞
            hits = pygame.sprite.spritecollide(player, enemies, True)
            for hit in hits:
                player.health -= 20
                # 生成新敌人
                enemy = Enemy()
                all_sprites.add(enemy)
                enemies.add(enemy)
                if player.health <= 0:
                    game_over = True
            
            # 绘制
            screen.fill(BLACK)
            
            # 绘制星星
            for star in stars:
                star.draw(screen)
            
            # 绘制所有精灵
            all_sprites.draw(screen)
            
            # 绘制分数和血条
            draw_text(screen, f"分数: {score}", 24, WINDOW_WIDTH // 2, 10)
            draw_health_bar(screen, 5, 5, player.health)
        else:
            show_game_over_screen(score)
            return  # 结束当前游戏循环
        
        # 刷新屏幕
        pygame.display.flip()

# 加载音效
shoot_sound, explosion_sound = load_sounds()

# 游戏循环
while True:
    show_start_screen()
    game_loop()

# 退出游戏
pygame.quit()
sys.exit()